package ru.compft.web.view;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import ru.compft.common.data.Module;
import ru.compft.common.data.ModulePage;
import ru.compft.common.services.ModuleService;
import ru.compft.common.utils.GlobalConstants;
import ru.compft.web.WebConst;
import ru.compft.web.utils.FacesUtils;
import ru.compft.web.utils.ViewUtils;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.event.ComponentSystemEvent;
import javax.servlet.ServletRequest;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * User: VVasiliev
 * Date: 14.06.12
 * Time: 13:32
 * Бин хранящий текущий модуль в системе, на странице которого находится пользователь
 */
@ManagedBean(name = WebConst.MODULE_VIEW)
@SessionScoped
public class ModuleView implements Serializable {
    private static final long serialVersionUID = 1304665814796224309L;

    private static final Logger logger = LoggerFactory.getLogger(ModuleView.class);

    private Module currentModule;
    private ModulePage currentModulePage;
    private List<String> pageCodeList;  // список всех кодов страниц для текущего модуля

    public Module getCurrentModule() {
        return currentModule;
    }

    public void setCurrentModule(Module currentModule) {
        this.currentModule = currentModule;
    }

    public ModulePage getCurrentModulePage() {
        return currentModulePage;
    }

    public void setCurrentModulePage(ModulePage currentModulePage) {
        this.currentModulePage = currentModulePage;
    }

    public List<String> getPageCodeList() {
        if (pageCodeList == null) pageCodeList = new ArrayList<String>();
        return pageCodeList;
    }

    public void setPageCodeList(List<String> pageCodeList) {
        this.pageCodeList = pageCodeList;
    }

    public String getCurrentPageCode() {
        final ServletRequest servletRequest = (ServletRequest) FacesUtils.getExternalContext().getRequest();
        final String tab = servletRequest.getParameter("tab");

//        System.out.println(" ------- getCurrentPageCode tab = " + tab);

        return getPageCodeList().contains(tab) ? tab : GlobalConstants.EMPTY;
    }

    public void loadModule(ComponentSystemEvent event) {
        final ServletRequest servletRequest = (ServletRequest) FacesUtils.getExternalContext().getRequest();
        final String tab = servletRequest.getParameter("tab");

        // если страница не задана, очистим ее
        if (!StringUtils.hasText(tab))
            setCurrentModulePage(null);

        final UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot();
        final String viewId = viewRoot.getViewId();
        final String code = ViewUtils.getModuleCodeByViewId(viewId);

        // Если модуль не поменялся, то нет смысла его перезагружать.
        // просто найдем его страницу и установим как текущую
        if (StringUtils.hasText(code)) {
            if (currentModule == null || !code.equals(currentModule.getCode())) {
                // обнулим предыдущий модуль и страницу если они были установлены
                clearAll();
                loadModule(code);
            }
        } else {
            // если в запросе нет модуля, очищаем все
            clearAll();
        }

        if (currentModule != null) {
            final List<ModulePage> modulePageList = currentModule.getPageList();
            boolean founded = false; // признак того, что страницу нашли
            if (!CollectionUtils.isEmpty(modulePageList)) {
                for (ModulePage modulePage : modulePageList) {
                    final String modulePageCode = modulePage.getCode();
                    if (!getPageCodeList().contains(modulePageCode)) {
                        getPageCodeList().add(modulePageCode);
                    }

                    if (modulePageCode.equals(tab)) {
                        setCurrentModulePage(modulePage);
                        founded = true;
                    }
                }
            }

            if (StringUtils.hasText(tab) && !founded) {
                pageNotFound(tab);
            }
        } else {
            moduleNotFound(code);
        }

//        System.out.println("MODULE = " + code);
//        System.out.println("PAGE = " + tab);
    }

    /**
     * Пишем сообщение, что страница не найдена
     *
     * @param tab
     */
    private void pageNotFound(String tab) {
        // Страница не найдена
        // todo сделать через файл messages
        FacesUtils.addErrorMessage(null, "Страница не найдена");
        if (logger.isDebugEnabled()) {
            logger.debug("ModulePage with code {" + tab + "} not found");
        }
    }

    /**
     * Пишем сообщение, что модуль не найден
     *
     * @param code
     */
    private void moduleNotFound(String code) {
        // Модуль не найден
        // todo сделать через файл messages
        FacesUtils.addErrorMessage(null, "Модуль не найден");
        if (logger.isDebugEnabled()) {
            logger.debug("Module with code {" + code + "} not found");
        }
    }

    /**
     * Загружаем модуль в качестве текущего по его пути
     *
     * @param code
     */
    private void loadModule(String code) {
        if (logger.isDebugEnabled()) {
            logger.debug("Try load module by code = " + code);
        }

        if (StringUtils.hasText(code)) {
            final ModuleService moduleService = (ModuleService) FacesUtils.getSpringBean(WebConst.MODULE_SERVICE);
            final Module module = moduleService.getModuleByCode(code);

            // устанавливаем путь к текущей странице
            // todo сделать ModulePermitter - проверку на доступность данного модуля для пользователя
            // todo иначе возможен прямой переход - "хакерская" атака
            if (module != null) {
                setCurrentModule(module);

                if (logger.isDebugEnabled()) {
                    logger.debug("Module {" + code + "} found and set as current");
                }
            }
        }
    }

    public void clearAll() {
        setCurrentModule(null);
        setCurrentModulePage(null);
        getPageCodeList().clear();
    }
}
